import java.util.concurrent.SynchronousQueue;

// java PrimeC
public class PrimeC {
	static final Thread.Builder.OfVirtual threadFactory = Thread.ofVirtual();

	static void go(Runnable r) {
		threadFactory.start(r);
	}

	static void generate(SynchronousQueue<Integer> ch) {
		try {
			//noinspection InfiniteLoopStatement
			for (int i = 2; ; i++)
				ch.put(i);
		} catch (Exception e) {
			//noinspection CallToPrintStackTrace
			e.printStackTrace();
		}
	}

	static void filter(SynchronousQueue<Integer> in, SynchronousQueue<Integer> out, int prime) {
		try {
			//noinspection InfiniteLoopStatement
			for (; ; ) {
				var i = in.take();
				if (i % prime != 0)
					out.put(i);
			}
		} catch (Exception e) {
			//noinspection CallToPrintStackTrace
			e.printStackTrace();
		}
	}

	public static void main(String[] args) throws InterruptedException {
		var count = args.length > 0 ? Integer.parseInt(args[0]) : 10000;
		go(() -> {
			var ch = new SynchronousQueue<Integer>(true);
			var ch0 = ch;
			go(() -> generate(ch0));
			try {
				for (int i = 0; ; ) {
					var prime = ch.take();
					if (++i == count) {
						System.out.println(prime);
						System.exit(0);
					}
					var ch1 = ch;
					var ch2 = new SynchronousQueue<Integer>(true);
					go(() -> filter(ch1, ch2, prime));
					ch = ch2;
				}
			} catch (Exception e) {
				//noinspection CallToPrintStackTrace
				e.printStackTrace();
			}
		});
		Thread.sleep(1_000_000L);
	}
}
